package com.yanqu.road.server.manager.activity.suitang.manager;

import com.yanqu.road.entity.activity.suitang.config.SuiTangCityConfig;
import com.yanqu.road.entity.activity.suitang.config.SuiTangCityTypeConfig;
import com.yanqu.road.entity.activity.suitang.config.SuiTangConfigSync;
import com.yanqu.road.entity.activity.suitang.data.*;
import com.yanqu.road.entity.activity.suitang.entity.battle.*;
import com.yanqu.road.entity.activity.suitang.entity.rank.CrossSuiTangRank;
import com.yanqu.road.entity.activity.suitang.entity.rank.CrossSuiTangRankListModel;
import com.yanqu.road.entity.activity.suitang.entity.team.CrossSuiTangTeam;
import com.yanqu.road.entity.activity.suitang.entity.union.CrossSuiTangUnionRound;
import com.yanqu.road.entity.activity.suitang.entity.user.CrossSuiTangUserRound;
import com.yanqu.road.entity.activity.suitang.enums.*;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.server.manager.activity.ActivityMgr;
import com.yanqu.road.utils.date.DateHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CrossSuiTangBattleActivityMgr extends CrossBaseActivityMgr {

    protected static Logger logger = LogManager.getLogger(CrossSuiTangBattleActivityMgr.class.getName());

    private List<String> hasBattleTask = new ArrayList<>();

    @Override
    public void init() {
        super.init();
        initCityBattleTask();
        logger.debug("【隋唐】战斗任务初始化完成");
    }

    // 缓存下最新的战斗结果,定时器会清除
    private Map<String, List<CrossSuiTangBattleResult>> battleResultMap = new ConcurrentHashMap<>();

    /*
     * 处理战斗
     */
    public CrossSuiTangBattleResult handleBattle(CrossSuiTangCity city, long userId, long enemyId, boolean isNpc) {
        CrossSuiTangBattleResult result = null;
        if (activity == null || city == null || city.getBattlefield() == null) {
            return null;
        }
        SuiTangConfigSync config = activity.getConfig();
        if (config == null || !ActivityMgr.activityInTime(config.getActivityInfo())) {
            return null;
        }
        if (isNpc) {
            // 进攻 npc
            if (!canAttackNpc(city, userId, enemyId)) {
                return null;
            }
            result = attackNpc(city, userId, enemyId);
        } else {
            if (!canAttackUser(city, userId, enemyId)) {
                return null;
            }
            result = attack(city, userId, enemyId);
        }
//        String scene = activity.getSceneKey(city.getCityId(), city.getWarType(), city.getActGroupId());
//        if (result != null && !hasBattleTask.contains(scene)) {
//            activity.addTask(new CrossSuiTangCityTask(activity, System.currentTimeMillis(),
//                    city.getCityId(), city.getActGroupId(), city.getWarType()
//            ));
//            hasBattleTask.add(scene);
//        }
        return result;
    }

    /*
     * attack
     */
    public CrossSuiTangBattleResult attack(CrossSuiTangCity city, long userId, long enemyId) {
        CrossSuiTangBattleResult result = new CrossSuiTangBattleResult();
        if (activity == null || city == null || city.getBattlefield() == null) {
            return null;
        }
        SuiTangConfigSync config = activity.getConfig();
        if (config == null || !ActivityMgr.activityInTime(config.getActivityInfo())) {
            return null;
        }

        CrossSuiTangBattlefield battlefield = city.getBattlefield();
        if (battlefield == null) {
            return null;
        }
        CrossSuiTangUserData attUser = activity.getUserData(userId);
        CrossSuiTangUserData enemyUser = activity.getUserData(enemyId);
        boolean attIsDef = attUser.getUnionUid().equals(city.getUnionId());
        boolean enemyIsDef = enemyUser.getUnionUid().equals(city.getUnionId());
        CrossSuiTangBattlefieldTeam attBattleTeam = attIsDef ? battlefield.getDefTeamMap().get(userId) : battlefield.getAtkTeamMap().get(userId);
        CrossSuiTangBattlefieldTeam enemyBattleTeam = enemyIsDef ? battlefield.getDefTeamMap().get(enemyId) : battlefield.getAtkTeamMap().get(enemyId);
        if (attBattleTeam == null || enemyBattleTeam == null) {
            return null;
        }

        // 加入交战队列
        synchronized (getCityLock(city)) {
            battlefield.getAttackingTeamMap().put(userId, attBattleTeam);
            battlefield.getAttackingTeamMap().put(enemyId, enemyBattleTeam);
            activity.getSyncActivityMgr().syncTeamToSelf(attUser.getTeam());
            activity.getSyncActivityMgr().syncTeamToSelf(enemyUser.getTeam());


            // 获取士兵数
            long attCount = attUser.getTeam().getSoldierNum();
            long enemyCount = enemyUser.getTeam().getSoldierNum();

            // 计算buff加成
            SuiTangCityConfig cityConfig = config.getCityConfigMap().get(city.getCityId());
            SuiTangCityTypeConfig cityTypeConfig = config.getCityTypeConfigMap().get(config.getCityTypeConfigKey(city.getWarType(), cityConfig.getType()));
            List<Integer> attBattleBuff = attIsDef ? getBattleBuffAddition(attUser.getUnionUid(), eSuiTangBuffType.Type3_DefCityBattleSpeedUp) : getBattleBuffAddition(attUser.getUnionUid(), eSuiTangBuffType.Type4_AttCityBattleSpeedDown);
            int attBattleBuffAdd = attBattleBuff.isEmpty() ? 0 : attBattleBuff.get(0);
            int attAddition = attIsDef ?
                    cityTypeConfig.getAddition() : 0;
            attAddition += attBattleBuffAdd;
            List<Integer> enemyBattleBuff = enemyIsDef ? getBattleBuffAddition(enemyUser.getUnionUid(), eSuiTangBuffType.Type3_DefCityBattleSpeedUp) : getBattleBuffAddition(enemyUser.getUnionUid(), eSuiTangBuffType.Type4_AttCityBattleSpeedDown);
            int enemyBattleBuffAdd = enemyBattleBuff.isEmpty() ? 0 : enemyBattleBuff.get(0);
            int enemyAddition = enemyIsDef ?
                    cityTypeConfig.getAddition() : 0;
            enemyAddition += enemyBattleBuffAdd;
            long attCountCalc = attCount * (1000 + attAddition) / 1000;
            long enemyCountCalc = enemyCount * (1000 + enemyAddition) / 1000;

            // 判断胜利方 1：被攻击者赢，2：攻击者赢
            int winType = attCountCalc == enemyCountCalc ? 0 : (attCountCalc > enemyCountCalc ? 2 : 1);
            if (winType == 0) {
                // 兵力相同，继续判断
                winType = attIsDef ? 2 : (enemyIsDef ? 1 : 0);
                if (winType == 0) {
                    winType = attBattleTeam.getTeam().getTime() <= enemyBattleTeam.getTeam().getTime() ? 2 : 1;
                }
            }

            // 损兵比例
            BigDecimal attCostPercent = winType != 2 ? BigDecimal.ONE : calcBattleCostPercent(attCountCalc, enemyCountCalc);
            BigDecimal enemyCostPercent = winType != 1 ? BigDecimal.ONE : calcBattleCostPercent(enemyCountCalc, attCountCalc);

            // 计算伤亡
            long attCost = BigDecimal.valueOf(attCount).multiply(attCostPercent).setScale(0, BigDecimal.ROUND_DOWN).longValue();
            long enemyCost = BigDecimal.valueOf(enemyCount).multiply(enemyCostPercent).setScale(0, BigDecimal.ROUND_DOWN).longValue();

            // 扣除伤亡
            long now = System.currentTimeMillis();
            int battleCd = winType == 2 ? config.getParamConfig().getSuiTangBattleProtectTime() : 0;
            long buffAtt = attBattleBuff.isEmpty() ? 0 : attBattleBuff.get(1) * DateHelper.SECOND_MILLIONS;
            buffAtt = getBattleBuffType(city, attUser.getUnionUid()).getValue() == eSuiTangBuffType.Type4_AttCityBattleSpeedDown.getValue() ? -buffAtt : buffAtt;
            long buffDef = enemyBattleBuff.isEmpty() ? 0 : enemyBattleBuff.get(1) * DateHelper.SECOND_MILLIONS;
            buffDef = getBattleBuffType(city, enemyUser.getUnionUid()).getValue() == eSuiTangBuffType.Type4_AttCityBattleSpeedDown.getValue() ? -buffDef : buffDef;
            attBattleTeam.setBattleCd(now + (config.getParamConfig().getSuiTangBattleTime() + battleCd) * DateHelper.SECOND_MILLIONS
                    + buffAtt + buffDef);
            attBattleTeam.setLastBattleTime(now + config.getParamConfig().getSuiTangBattleTime() * DateHelper.SECOND_MILLIONS
                    + buffAtt + buffDef);
            CrossSuiTangTeam attTeam = attUser.getTeam();
            attTeam.setSoldierNum(attCount - attCost);
            boolean isPingShouAtt = attTeam.getSoldierNum() == 0 && winType == 2;
            if (isPingShouAtt) {
                // 胜利方空血，要给他最后留1滴血，其他计算不变，战损要减去1
                attTeam.setSoldierNum(1);
            }
            attUser.setUpdateOption();

            battleCd = winType == 1 ? config.getParamConfig().getSuiTangBattleProtectTime() : 0;
            enemyBattleTeam.setBattleCd(now + (config.getParamConfig().getSuiTangBattleTime() + battleCd) * DateHelper.SECOND_MILLIONS
                    + buffAtt + buffDef);
            enemyBattleTeam.setLastBattleTime(now + config.getParamConfig().getSuiTangBattleTime() * DateHelper.SECOND_MILLIONS
                    + buffAtt + buffDef);
            CrossSuiTangTeam enemyTeam = enemyUser.getTeam();
            enemyTeam.setSoldierNum(enemyCount - enemyCost);
            boolean isPingShouEnemy = enemyTeam.getSoldierNum() == 0 && winType == 1;
            if (isPingShouEnemy) {
                // 胜利方空血，要给他最后留1滴血，其他计算不变，战损要减去1
                enemyTeam.setSoldierNum(1);
            }
            enemyUser.setUpdateOption();

            // 加战功
            long attZhanGong = calcZhanGong(attCost, attCount);
            long enemyZhanGong = calcZhanGong(enemyCost, enemyCount);
            addZhanGong(attUser, attZhanGong, now);
            addZhanGong(enemyUser, enemyZhanGong, now);

            // 战场排行
            if (isPingShouAtt) {
                // 胜利方空血，要给他最后留1滴血，其他计算不变，战损要减去1
                attCost -= 1;
            }
            if (isPingShouEnemy) {
                // 胜利方空血，要给他最后留1滴血，其他计算不变，战损要减去1
                enemyCost -= 1;
            }
            activity.getRankActivityMgr().updateWarUserRank(city.getCityId(), userId, attZhanGong, enemyCost, attBattleTeam.getTeam().getTime());
            activity.getRankActivityMgr().updateUserRank(userId, attUser.getZhanGong(), now);
            activity.getRankActivityMgr().updateWarUserRank(city.getCityId(), enemyId, enemyZhanGong, attCost, enemyBattleTeam.getTeam().getTime());
            activity.getRankActivityMgr().updateUserRank(enemyId, enemyUser.getZhanGong(), now);

            // 连胜处理
            CrossSuiTangBattlefieldTeam winner = winType == 1 ? enemyBattleTeam : attBattleTeam;
            CrossSuiTangBattlefieldTeam loser = winType == 1 ? attBattleTeam : enemyBattleTeam;
            int winTimes = 0;
            if (winType == 1) {
                if (enemyBattleTeam.getTeam() != null) {
                    winTimes = enemyTeam.getWinTimes();
                }
            } else {
                if (attBattleTeam.getTeam() != null) {
                    winTimes = attTeam.getWinTimes();
                }
            }

            // 处理战斗次数,疲敝状态
            handleCurBattleNum(winner, loser);

            // 生成战报
            recordUserWarReport(attBattleTeam, enemyBattleTeam, attAddition, enemyAddition, attCount, enemyCount, attCost, enemyCost, attZhanGong, enemyZhanGong,
                    now, winType, city.getCityId());

            // 战斗结果
            result.setAtk(attBattleTeam);
            result.setDef(enemyBattleTeam);
            result.setCity(city);
            result.setBattlefield(battlefield);
            result.setAtkHpReduce(attCost);
            result.setDefHpReduce(enemyCost);
            result.setWinTimes(winTimes + 1);
            result.setWinType(winType);
            result.setAtkZhanGong(attZhanGong);
            result.setDefZhanGong(enemyZhanGong);
            result.setBattleStartTime(now);
            result.setBattleEndTime(attBattleTeam.getLastBattleTime());
            String scene = activity.getSceneKey(city.getCityId(), city.getWarType(), city.getActGroupId());
            addBattleResultMap(scene, result);
            activity.getSyncActivityMgr().addNeedSyncBattleResult(result, scene);

            // 保存下这次战斗相关的城市内容
            if (city.getStatus() != 1) {
                city.setStatus(1);
                city.setChangeStatusTime(now);
                city.setUpdateDefensePeopleTime(now);
                city.setTeamRecoveryBeginTime(0);
                activity.getSyncActivityMgr().syncCity(city, false);
            }
            battlefield.setLastBattleTime(attBattleTeam.getLastBattleTime());

            battleAfter(city, winner, loser, result);
        }
        CrossSuiTangData crossSuiTangData = activity.getCrossSuiTangData();
        crossSuiTangData.setUpdateOption();
        city.setUpdateOption();
        return result;
    }

    /*
     * 获取战斗buff类型
     */
    private eSuiTangBuffType getBattleBuffType(CrossSuiTangCity city, String unionId) {
        return city.getUnionId().equals(unionId) ? eSuiTangBuffType.Type3_DefCityBattleSpeedUp : eSuiTangBuffType.Type4_AttCityBattleSpeedDown;
    }

    /*
     * 处理连胜
     */
    private void handleWinTimes(CrossSuiTangBattlefieldTeam winner, CrossSuiTangBattlefieldTeam loser) {
        long now = System.currentTimeMillis();
        if (winner.getTeam() != null && loser.getTeam() != null) {
            // 交战双方都为玩家，则计入连胜
            CrossSuiTangTeam team = getTeam(winner.getTeamNo());
            if (team != null) {
//                if (team.getWinTime() + 5 * DateHelper.MINUTE_MILLIONS < now) {
//                    team.setWinTimes(0);
//                }
                team.setWinTime(now);
                team.setWinTimes(team.getWinTimes() + 1);
            }
        }
        if (loser.getTeam() != null) {
            CrossSuiTangTeam team = getTeam(loser.getTeamNo());
            if (team != null) {
                team.setWinTime(now);
                team.setWinTimes(0);
            }
        }
    }

    /*
     * 处理战斗次数,疲敝状态
     */
    private void handleCurBattleNum(CrossSuiTangBattlefieldTeam winner, CrossSuiTangBattlefieldTeam loser) {
        if (winner.getTeam() != null) {
            // 交战双方都为玩家，则计入连胜
            CrossSuiTangTeam team = getTeam(winner.getTeamNo());
            if (team != null) {
                team.setCurBattleNum(team.getCurBattleNum() + 1);
            }
        }
        if (loser.getTeam() != null) {
            CrossSuiTangTeam team = getTeam(loser.getTeamNo());
            if (team != null) {
                team.setCurBattleNum(team.getCurBattleNum() + 1);
            }
        }
    }

    /*
     * 回城
     */
    public void toHomeCity(CrossSuiTangUserData userData) {
        CrossSuiTangUnionRound unionRoundData = getUnionRoundData(userData.getUnionUid());
        if (unionRoundData != null) {
            userData.getTeam().setFromCityId(unionRoundData.getHomeId());
            userData.getTeam().setCityId(unionRoundData.getHomeId());
            // 回家了改下时间
            userData.getTeam().setArriveTime(System.currentTimeMillis());
            userData.getTeam().setCurBattleNum(0);
            userData.setUpdateOption();
            CrossSuiTangCity homeCity = getCurCity(userData.getUserId(), unionRoundData.getHomeId());
            activity.getSyncActivityMgr().syncCity(homeCity, false);
//            if (homeCity != null) {
//                homeCity.getBattlefield().getDefTeamMap().put(userData.getUserId(), new CrossSuiTangBattlefieldTeam(new CrossSuiTangTeamArrive(userData.getUserId(), 0)));
//            }
        }
    }

    /*
     * addZhanGong
     */
    public void addZhanGong(CrossSuiTangUserData user, long zhanGong, long time) {
        user.setZhanGong(user.getZhanGong() + zhanGong);
        user.setZhanGongTime(time);
        CrossSuiTangUserRound curUserRound = getCurUserRound(user.getUserId());
        if (curUserRound != null) {
            curUserRound.getScore().getAndAdd(zhanGong);
        }
        user.setUpdateOption();
        // 通知游戏服更新condition成就
        activity.getSyncActivityMgr().notifyConditionChange(user.getUserId(), eGamePlayerEventType.SuiTangUserZhanGong, user.getZhanGong(), "");
    }

    /*
     * attackNpc
     */
    public CrossSuiTangBattleResult attackNpc(CrossSuiTangCity city, long userId, long enemyId) {
        CrossSuiTangBattleResult result = new CrossSuiTangBattleResult();
        if (activity == null || city == null || city.getBattlefield() == null) {
            return null;
        }
        SuiTangConfigSync config = activity.getConfig();
        if (config == null || !ActivityMgr.activityInTime(config.getActivityInfo())) {
            return null;
        }
        CrossSuiTangBattlefield battlefield = city.getBattlefield();
        if (battlefield == null) {
            return null;
        }
        CrossSuiTangUserData attUser = activity.getUserData(userId);
        CrossSuiTangBattlefieldTeam attBattleTeam = battlefield.getAtkTeamMap().get(userId);
        CrossSuiTangBattlefieldTeam enemyBattleTeam = battlefield.getDefTeamMap().get(enemyId);
        if (attBattleTeam == null || enemyBattleTeam == null) {
            return null;
        }

        // 加入交战队列
        synchronized (getCityLock(city)) {
            battlefield.getAttackingTeamMap().put(userId, attBattleTeam);
            battlefield.getAttackingTeamMap().put(enemyId, enemyBattleTeam);
            activity.getSyncActivityMgr().syncTeamToSelf(attUser.getTeam());


            // 获取士兵数
            long attCount = attUser.getTeam().getSoldierNum();
            long enemyCount = enemyBattleTeam.getSoldierNum();

            // 计算buff加成
            SuiTangCityConfig cityConfig = config.getCityConfigMap().get(city.getCityId());
            SuiTangCityTypeConfig cityTypeConfig = config.getCityTypeConfigMap().get(config.getCityTypeConfigKey(city.getWarType(), cityConfig.getType()));
            List<Integer> attBattleBuffAddition = getBattleBuffAddition(attUser.getUnionUid(), eSuiTangBuffType.Type4_AttCityBattleSpeedDown);
            int attAddition = attBattleBuffAddition.isEmpty() ? 0 : attBattleBuffAddition.get(0);
            List<Integer> enemyBattleBuffAddition = getBattleBuffAddition(city.getUnionId(), eSuiTangBuffType.Type3_DefCityBattleSpeedUp);
            int enemyAddition = enemyBattleBuffAddition.isEmpty() ? cityTypeConfig.getAddition() : enemyBattleBuffAddition.get(0) + cityTypeConfig.getAddition();
            long attCountCalc = attCount * (1000 + attAddition) / 1000;
            long enemyCountCalc = enemyCount * (1000 + enemyAddition) / 1000;

            // 判断胜利方 1：被攻击者赢，2：攻击者赢
            int winType = attCountCalc == enemyCountCalc ? 0 : (attCountCalc > enemyCountCalc ? 2 : 1);
            if (winType == 0) {
                // 兵力相同，玩家胜利
                winType = 2;
            }

            // 损兵比例
            BigDecimal attCostPercent = winType != 2 ? BigDecimal.ONE : calcBattleCostPercent(attCountCalc, enemyCountCalc);
            BigDecimal enemyCostPercent = winType != 1 ? BigDecimal.ONE : calcBattleCostPercent(enemyCountCalc, attCountCalc);

            // 计算伤亡
            long attCost = BigDecimal.valueOf(attCount).multiply(attCostPercent).setScale(0, BigDecimal.ROUND_DOWN).longValue();
            long enemyCost = BigDecimal.valueOf(enemyCount).multiply(enemyCostPercent).setScale(0, BigDecimal.ROUND_DOWN).longValue();

            // 扣除伤亡
            long now = System.currentTimeMillis();
            int battleCd = winType == 2 ? config.getParamConfig().getSuiTangBattleProtectTime() : 0;
            long buffAtt = attBattleBuffAddition.isEmpty() ? 0 : attBattleBuffAddition.get(1) * DateHelper.SECOND_MILLIONS;
            buffAtt = getBattleBuffType(city, attUser.getUnionUid()).getValue() == eSuiTangBuffType.Type4_AttCityBattleSpeedDown.getValue() ? -buffAtt : buffAtt;
            long buffDef = enemyBattleBuffAddition.isEmpty() ? 0 : enemyBattleBuffAddition.get(1) * DateHelper.SECOND_MILLIONS;
            buffDef = getBattleBuffType(city, city.getUnionId()).getValue() == eSuiTangBuffType.Type4_AttCityBattleSpeedDown.getValue() ? -buffDef : buffDef;
            attBattleTeam.setBattleCd(now + (config.getParamConfig().getSuiTangBattleTime() + battleCd) * DateHelper.SECOND_MILLIONS
                    + buffAtt + buffDef);
            attBattleTeam.setLastBattleTime(now + config.getParamConfig().getSuiTangBattleTime() * DateHelper.SECOND_MILLIONS
                    + buffAtt + buffDef);
            CrossSuiTangTeam attTeam = attUser.getTeam();
            attTeam.setSoldierNum(attCount - attCost);
            boolean isPingShouAtt = attTeam.getSoldierNum() == 0 && winType == 2;
            if (isPingShouAtt) {
                // 胜利方空血，要给他最后留1滴血，其他计算不变
                attTeam.setSoldierNum(1);
            }
            attUser.setUpdateOption();


            battleCd = /*winType == 1 ? config.getParamConfig().getSuiTangBattleProtectTime() : */0;    // 策划确定，npc不生效保护cd
            enemyBattleTeam.setBattleCd(now + (config.getParamConfig().getSuiTangBattleTime() + battleCd) * DateHelper.SECOND_MILLIONS
                    + buffAtt + buffDef);
            enemyBattleTeam.setLastBattleTime(now + config.getParamConfig().getSuiTangBattleTime() * DateHelper.SECOND_MILLIONS
                    + buffAtt + buffDef);
            enemyBattleTeam.setSoldierNum(Math.max(enemyCount - enemyCost, 0));

            // 加战功
            long attZhanGong = calcZhanGong(attCost, attCount);
            addZhanGong(attUser, attZhanGong, now);

            // 排行
            if (isPingShouAtt) {
                // 胜利方空血，要给他最后留1滴血，其他计算不变，战损要减去1
                attCost -= 1;
            }
            activity.getRankActivityMgr().updateWarUserRank(city.getCityId(), userId, attZhanGong, enemyCost, attBattleTeam.getTeam().getTime());
            activity.getRankActivityMgr().updateUserRank(userId, attUser.getZhanGong(), now);
            //activity.getRankActivityMgr().updateUnionRank(attUser.getUnionUid(), attZhanGong, now);

            // 连胜处理
            CrossSuiTangBattlefieldTeam winner = winType == 1 ? enemyBattleTeam : attBattleTeam;
            CrossSuiTangBattlefieldTeam loser = winType == 1 ? attBattleTeam : enemyBattleTeam;
            int winTimes = 0;
            if (winType == 1) {
                if (enemyBattleTeam.getTeam() != null) {
                    winTimes = getTeam(enemyId).getWinTimes();
                }
            } else {
                if (attBattleTeam.getTeam() != null) {
                    winTimes = attTeam.getWinTimes();
                }
            }

            // 处理战斗次数,疲敝状态
            handleCurBattleNum(winner, loser);

            // 生成战报
//        recordUserWarReport(attBattleTeam, enemyBattleTeam, attAddition, enemyAddition, attCount, enemyCount, attCost, enemyCost, attZhanGong, 0,
//                now, winType, city.getCityId());

            // 战斗结果
            result.setAtk(attBattleTeam);
            result.setDef(enemyBattleTeam);
            result.setCity(city);
            result.setBattlefield(battlefield);
            result.setAtkHpReduce(attCost);
            result.setDefHpReduce(enemyCost);
            result.setWinTimes(winTimes);
            result.setWinType(winType);
            result.setAtkZhanGong(attZhanGong);
            result.setDefZhanGong(0);
            result.setBattleStartTime(now);
            result.setBattleEndTime(attBattleTeam.getLastBattleTime());
            String scene = activity.getSceneKey(city.getCityId(), city.getWarType(), city.getActGroupId());
            addBattleResultMap(scene, result);
            activity.getSyncActivityMgr().addNeedSyncBattleResult(result, scene);
//            logger.debug("attCost:{}", attCost);
//            logger.debug("enemyCost:{}", enemyCost);
//            logger.debug("attZhanGong:{}", attZhanGong);

            // 保存下这次战斗相关的城市内容
            if (city.getStatus() != 1) {
                city.setStatus(1);
                city.setChangeStatusTime(now);
                city.setUpdateDefensePeopleTime(now);
                city.setTeamRecoveryBeginTime(0);
                activity.getSyncActivityMgr().syncCity(city, false);
            }
            battlefield.setLastBattleTime(attBattleTeam.getLastBattleTime());

            battleAfter(city, winner, loser, result);
        }

        CrossSuiTangData crossSuiTangData = activity.getCrossSuiTangData();
        crossSuiTangData.setUpdateOption();
        city.setUpdateOption();
        return result;
    }

    /*
     * 战斗定时任务
     */
    public void crossSuiTangCityTask(int cityId, eSuiTangWarType warType, int actGroupId) {
        try {
            if (getCity(warType, actGroupId, cityId) == null) {
                return;
            }
            long now = System.currentTimeMillis();

            CrossSuiTangCity city = getCity(warType, actGroupId, cityId);
            if (city == null) {
                return;
            }
            boolean needSync = false;
            synchronized (getCityLock(city)) {
                int oldCityStatus = city.getStatus();
                // 清除战斗队列
                boolean aSync = CleanupBattleAttackingTeam(city);
                // 检查下城市的状态
                boolean bSync = handleCityStatus(city, oldCityStatus, now);
                // 清除下战斗结果
                boolean cSync = CleanupResultMap(city);
                needSync = aSync || bSync || cSync;
            }
            if (needSync) {
                activity.getSyncActivityMgr().syncCity(city, true);
            }
        } catch (Exception e) {
            logger.error("crossSuiTangCityTask err", e);
        }/* finally {
            activity.addTask(new CrossSuiTangCityTask(activity, System.currentTimeMillis() + 1 * DateHelper.SECOND_MILLIONS, cityId, actGroupId, warType));
        }*/
    }

    /*
     * 处理城池状态
     */
    public boolean handleCityStatus(CrossSuiTangCity city, int oldCityStatus, long time) {
        boolean needSync = false;
        if (city.getStatus() == 0) {
            if (oldCityStatus == 1) {
                if (!city.getNpcGuardList().isEmpty()) {
                    needSync = true;
                    city.setLastRecoveryExtraTeamTime(time);
                    // 生成战报，这里生成，一定是防守方赢；攻击方赢的话，直接在战斗结束时生成。
                    recordCityWarReport(city, true, city.getUnionId(), city.getUnionId());
                    if (!city.getUnionId().isEmpty()) {
                        // 有归属的才生成跑马灯
                        activity.getSyncActivityMgr().syncTopMsg(true, false, "", city.getUnionId(), city);
                    }
                }
            }
        }
        // 根据地计算守军
        long nowTime = System.currentTimeMillis();
        SuiTangCityConfig cityConfig = activity.getConfig().getCityConfigMap().get(city.getCityId());
        if (cityConfig != null && cityConfig.getType() == eSuiTangCityType.CITY_TYPE_HOME.getType()) {
            if (city.getStatus() == 0 && city.getNeedDefensePeople() > 1) {
                // 和平状态，持续扣除阻击人数
                // 过了多少毫秒
                long offsetTime = nowTime - city.getUpdateDefensePeopleTime();
                // 扣除了多少个
                long offsetCount = offsetTime / (activity.getConfig().getParamConfig().getWarDefensePeople().get(1) * DateHelper.SECOND_MILLIONS);
                if (offsetCount > 0) {
                    // 最低只能降到1
                    city.setNeedDefensePeople(Math.max(1, city.getNeedDefensePeople() - (int) offsetCount));
                    city.setUpdateDefensePeopleTime(nowTime);
                    logger.debug("【隋唐阻击日志】和平状态,持续扣除阻击人数,活动id:{},分组id:{},战场分组id:{},城市id:{},所需阻击人数:{}", activity.getConfig().getActivityInfo().getActivityId(), activity.getGroupId(), city.getActGroupId(), city.getCityId(), city.getNeedDefensePeople());
                    needSync = true;
                }
            } else if (city.getStatus() == 1 && city.getNeedDefensePeople() < activity.getConfig().getParamConfig().getWarDefensePeople().get(2)) {
                // 交战状态，持续增加阻击人数
                // 过去了多少毫秒
                long offsetTime = nowTime - city.getUpdateDefensePeopleTime();
                // 增加了多少个
                long offsetCount = offsetTime / (activity.getConfig().getParamConfig().getWarDefensePeople().get(0) * DateHelper.SECOND_MILLIONS);
                if (offsetCount > 0) {
                    // 最多只能加到xx
                    city.setNeedDefensePeople(Math.max(1, Math.min(activity.getConfig().getParamConfig().getWarDefensePeople().get(2), city.getNeedDefensePeople() + (int) offsetCount)));
                    city.setUpdateDefensePeopleTime(nowTime);
                    logger.debug("【隋唐阻击日志】交战状态,持续增加阻击人数,活动id:{},分组id:{},战场分组id:{},城市id:{},所需阻击人数:{}", activity.getConfig().getActivityInfo().getActivityId(), activity.getGroupId(), city.getActGroupId(), city.getCityId(), city.getNeedDefensePeople());
                    needSync = true;
                }
            }
//            logger.error("城市id:{},当前阻击人数:{}", city.getCityId(), city.getNeedDefensePeople());
        }
        return needSync;
    }

    /*
     * 生成个人战报
     */
    public void recordUserWarReport(CrossSuiTangBattlefieldTeam atkTeam, CrossSuiTangBattlefieldTeam def,
                                    int atkAddition, int defAddition,
                                    long atkCount, long defCount,
                                    long atkCost, long defCost,
                                    long atkZhanGong, long defZhanGong,
                                    long battleTime, int winType, int cityId
    ) {
        CrossSuiTangUserWarReportData userReport = new CrossSuiTangUserWarReportData();
        if (def.getTeam() == null) {
            userReport.setUserIdDef(0);
        } else {
            CrossSuiTangTeam defTeam = getTeam(def.getTeamNo());
            userReport.setUserIdDef(defTeam.getUserId());
        }
        userReport.setActivityId(activity.getConfig().getActivityInfo().getActivityId());
        userReport.setGroupId(activity.getGroupId());
        userReport.setUserIdAct(atkTeam.getTeamNo());
        userReport.setDefSoldierNum(defCount);
        userReport.setActSoldierNum(atkCount);
        userReport.setDefAddition(defAddition);
        userReport.setActAddition(atkAddition);
        userReport.setDefZhanGong(defZhanGong);
        userReport.setActZhanGong(atkZhanGong);
        userReport.setDefDieSoldierNum(defCost);
        userReport.setActDieSoldierNum(atkCost);
        userReport.setWinUserId(winType);
        userReport.setTime(battleTime);
        userReport.setCityId(cityId);
        userReport.setCityUnionId(getCurCity(atkTeam.getTeamNo(), cityId).getUnionId());
        activity.addUserWarReportMemory(userReport);
        activity.addUserWarReport(userReport);
        List<Long> syncList = new ArrayList<>();
        syncList.add(def.getTeamNo());
        syncList.add(atkTeam.getTeamNo());
        addRedDotToAll(syncList, eSuiTangRedDotType.Type2_UserWarReport);
    }

    /*
     * 生成城池战报
     */
    public void recordCityWarReport(CrossSuiTangCity city, boolean defWin, String winUnionId, String defUnionId) {
        Map<String, CrossSuiTangRankListModel> cityRankMap = getCityRankMap(city);
        if (cityRankMap == null || cityRankMap.isEmpty()) {
            return;
        }
        Set<String> atkSet = new HashSet<>();
        LinkedList<CrossSuiTangBattlefieldRank> atkRank = new LinkedList<>();
        LinkedList<CrossSuiTangBattlefieldRank> defRank = new LinkedList<>();
        for (Map.Entry<String, CrossSuiTangRankListModel> entry : cityRankMap.entrySet()) {
            String unionId = entry.getKey();
            CrossSuiTangRankListModel rankList = entry.getValue();
            for (CrossSuiTangRank rank : rankList.getRankList()) {
                if (Objects.equals(unionId, defUnionId)) {
                    if (defRank.size() <= 3) {
                        defRank.add(new CrossSuiTangBattlefieldRank(Long.parseLong(rank.getId()), rank.getValue(), rank.getAbility()));
                    }
                } else {
                    atkSet.add(unionId);
                    if (atkRank.size() <= 3) {
                        atkRank.add(new CrossSuiTangBattlefieldRank(Long.parseLong(rank.getId()), rank.getValue(), rank.getAbility()));
                    }
                }
            }
        }
        cityRankMap.clear();

        // 生成战报
        CrossSuiTangCityWarReportData reportData = new CrossSuiTangCityWarReportData();
        reportData.setActivityId(activity.getConfig().getActivityId());
        reportData.setGroupId(activity.getGroupId());
        reportData.setAtkCampId(new ArrayList<>(atkSet));
        reportData.setDefCampId(defUnionId);
        reportData.setType(defWin ? 2 : 1);
        reportData.setCityId(city.getCityId());
        reportData.setTime(city.getBattlefield() == null ? 0 : city.getBattlefield().getLastBattleTime());
        reportData.setAtkRankList(atkRank);
        reportData.setDefRankList(defRank);
        reportData.setWinCampId(winUnionId);
        activity.addCityWarReportMemory(reportData);
        activity.addCityWarReport(reportData);
        activity.getSyncActivityMgr().syncCityWarReportToActGroup(reportData, city);

        // 同步红点
        ArrayList<String> unions = new ArrayList<>(atkSet);
        unions.add(defUnionId);
        for (String unionId : unions) {
            if (!unionId.isEmpty()) {
                addRedDotToAll(new ArrayList<>(getUnionJoin(unionId).getMemberMap().keySet()), eSuiTangRedDotType.Type3_CityWarReport);
            }
        }
    }

    /*
     * 清理战斗队列
     */
    public boolean CleanupBattleAttackingTeam(CrossSuiTangCity city) {
        boolean needSync = false;
        long now = System.currentTimeMillis();
        CrossSuiTangBattlefield battlefield = city.getBattlefield();
        if (battlefield != null && city.getStatus() != 0 && (battlefield.getLastBattleTime() + activity.getConfig().getParamConfig().getWarFinishTime() * DateHelper.SECOND_MILLIONS) < now) {
            city.setStatus(0);
            city.setChangeStatusTime(now);
            // 变为和平状态需要立即-1
            city.setNeedDefensePeople(Math.max(1, city.getNeedDefensePeople() - 1));
            logger.debug("【隋唐阻击日志】变为和平状态需要立即-1,活动id:{},分组id:{},战场分组id:{},城市id:{},所需阻击人数:{}", activity.getConfig().getActivityInfo().getActivityId(), activity.getGroupId(), city.getActGroupId(), city.getCityId(), city.getNeedDefensePeople());
            city.setUpdateDefensePeopleTime(now);
            needSync = true;
        }
        List<Long> removeList = new ArrayList<>();
        Map<Long, CrossSuiTangBattlefieldTeam> attackingMap = city.getBattlefield().getAttackingTeamMap();
        if (attackingMap != null && !attackingMap.isEmpty()) {
            for (CrossSuiTangBattlefieldTeam team : attackingMap.values()) {
                if (team != null && now > team.getLastBattleTime()) {
                    removeList.add(team.getTeamNo());
                }
            }
            for (long id : removeList) {
                attackingMap.remove(id);
            }
            city.setUpdateOption();
        }

        removeList.clear();
        Map<Long, CrossSuiTangBattlefieldTeam> attMap = city.getBattlefield().getAtkTeamMap();
        if (attMap != null && !attMap.isEmpty()) {
            for (CrossSuiTangBattlefieldTeam team : attMap.values()) {
                if (team != null && team.getTeam() != null) {
                    CrossSuiTangTeam tmpTeam = getTeam(team.getTeamNo());
                    if (tmpTeam.getCityId() != city.getCityId() || isOut(team.getTeamNo())) {
                        removeList.add(team.getTeamNo());
                    }
                }
            }
            for (long id : removeList) {
                attMap.remove(id);
            }
            city.setUpdateOption();
        }

        removeList.clear();
        Map<Long, CrossSuiTangBattlefieldTeam> defTeamMap = city.getBattlefield().getDefTeamMap();
        if (defTeamMap != null && !defTeamMap.isEmpty()) {
            for (CrossSuiTangBattlefieldTeam team : defTeamMap.values()) {
                if (team != null && team.getTeam() != null) {
                    CrossSuiTangTeam tmpTeam = getTeam(team.getTeamNo());
                    if (tmpTeam.getCityId() != city.getCityId() || isOut(team.getTeamNo())) {
                        removeList.add(team.getTeamNo());
                    }
                }
            }
            for (long id : removeList) {
                defTeamMap.remove(id);
            }
            city.setUpdateOption();
        }

        return needSync;
    }

    /*
     * 清理战斗结果
     */
    public boolean CleanupResultMap(CrossSuiTangCity city) {
        boolean needSync = false;
        List<CrossSuiTangBattleResult> removeList = new ArrayList<>();
        List<CrossSuiTangBattleResult> resultList = battleResultMap.get(activity.getSceneKey(city.getCityId(), city.getWarType(), city.getActGroupId()));
        if (resultList != null && !resultList.isEmpty()) {
            for (CrossSuiTangBattleResult battleResult : resultList) {
                if (battleResult == null
                        || System.currentTimeMillis() <= battleResult.getBattleEndTime()
                        || battleResult.getCity().getCityId() != city.getCityId()
                        || battleResult.getCity().getWarType() != city.getWarType()
                        || battleResult.getCity().getActGroupId() != city.getActGroupId()) {
                    continue;
                }
                removeList.add(battleResult);
                int logType = 0;
                // 失败方回城
                if (battleResult.getWinType() == 1) {
                    // 被攻击者赢
                    handleLoser(battleResult, battleResult.getAtk().getTeamNo());
                    handleWinTimes(battleResult.getDef(), battleResult.getAtk());
                    needSync = true;
                } else {
                    // 攻击者赢
                    if (battleResult.getDef().getTeam() == null) {
                        // npc
                        battleResult.getCity().getNpcGuardList().remove(battleResult.getDef().getTeamNo());
                        battleResult.getBattlefield().getDefTeamMap().remove(battleResult.getDef().getTeamNo());
                        if (battleResult.getCity().getNpcGuardList().isEmpty()) {
                            CrossSuiTangUserData attUser = activity.getUserData(battleResult.getAtk().getTeamNo());
                            activity.getCityActivityMgr().crossCityChangeUnion(attUser.getUnionUid(), battleResult.getCity().getUnionId(), city);
                            logType = 1;
                        }
                        handleYinShan(battleResult.getCity());
                    } else {
                        handleLoser(battleResult, battleResult.getDef().getTeamNo());
                    }
                    handleWinTimes(battleResult.getAtk(), battleResult.getDef());
                    needSync = true;
                }
                if (battleResult.getDef().getTeam() != null) {
                    if (!activity.getMapActivityMgr().soldierLimit(getTeam(battleResult.getDef().getTeamNo()))) {
                        getTeam(battleResult.getDef().getTeamNo()).setCurBattleNum(0);
                    }
                    handleNextMoveCity(battleResult.getDef(), battleResult.getWinType() == 1);
                }
                if (battleResult.getAtk().getTeam() != null) {
                    if (!activity.getMapActivityMgr().soldierLimit(getTeam(battleResult.getAtk().getTeamNo()))) {
                        getTeam(battleResult.getAtk().getTeamNo()).setCurBattleNum(0);
                    }
                    handleNextMoveCity(battleResult.getAtk(), battleResult.getWinType() == 2);
                }

                activity.getLogActivityMgr().addOccupyLog(battleResult, battleResult.getCity(), logType);
            }
            if (!removeList.isEmpty() && !resultList.isEmpty()) {
                for (CrossSuiTangBattleResult battleResult : removeList) {
                    resultList.remove(battleResult);
                    activity.getSyncActivityMgr().syncBattleResultMsg(battleResult.getCity());
                    if (battleResult.getAtk().getTeam() != null) {
                        activity.getSyncActivityMgr().syncTeamToSelf(getTeam(battleResult.getAtk().getTeamNo()));
                    }
                    if (battleResult.getDef().getTeam() != null) {
                        activity.getSyncActivityMgr().syncTeamToSelf(getTeam(battleResult.getDef().getTeamNo()));
                    }
                }
            }
        }
        return needSync;
    }

    /*
     * 特殊处理阴山
     */
    private void handleYinShan(CrossSuiTangCity city) {
        int yinShan = 6001;
        int yinShanType = 6;
        if (city.getCityId() != yinShan) {
            return;
        }
        CrossSuiTangBattlefield battlefield = city.getBattlefield();
        if (battlefield == null || battlefield.getDefTeamMap() == null || city.getNpcGuardList() == null) {
            return;
        }
        SuiTangCityTypeConfig cityTypeConfig = getCityTypeConfig(city);
        if (cityTypeConfig == null || cityTypeConfig.getType() != yinShanType) {
            return;
        }
        if (city.getNpcGuardList().size() >= cityTypeConfig.getTeamNum(calcRound())) {
            return;
        }
        // 起始 npc Id
        long npcId = city.getNpcGuardList().get(city.getNpcGuardList().size() - 1) + 1;
        for (int i = 0; i < cityTypeConfig.getTeamNum(calcRound()) - city.getNpcGuardList().size(); i++) {
            battlefield.getDefTeamMap().put((long) i + npcId, new CrossSuiTangBattlefieldTeam(i + npcId, cityTypeConfig.getSoldierNum(calcRound()), 1));
            city.getNpcGuardList().add((long) i + npcId);
        }
    }

    /*
     * 战后处理输家
     */
    private void handleLoser(CrossSuiTangBattleResult result, long loserId) {
        synchronized (getCityLock(result.getCity())) {
            result.getBattlefield().getAtkTeamMap().remove(loserId);
            result.getBattlefield().getDefTeamMap().remove(loserId);
        }
        toHomeCity(activity.getUserData(loserId));
    }

    /*
     * 处理预设移动城市
     */
    private void handleNextMoveCity(CrossSuiTangBattlefieldTeam battleTeam, boolean isWinner) {
        if (battleTeam == null || battleTeam.getTeam() == null) {
            return;
        }
        CrossSuiTangTeam team = getTeam(battleTeam.getTeamNo());
        if (team == null) {
            return;
        }
        // 先检查下有没有预设目标
        CrossSuiTangCity nextMoveCity = activity.getMapActivityMgr().getNextMoveCity(team.getUserId());
        if (nextMoveCity != null) {
            // 先清掉城市
            activity.getMapActivityMgr().clearNextMoveCity(team.getUserId());
            if (team.isAutoMove()) {
                team.setTargetCityId(nextMoveCity.getCityId());
                if (isWinner) {
                    activity.getMapActivityMgr().moveToCity(team, nextMoveCity.getCityId());
                } else {
                    activity.getMapActivityMgr().autoMoveToCity(team, team.getTargetCityId());
                }
            } else {
                team.setTargetCityId(0);
                activity.getMapActivityMgr().moveToCity(team, nextMoveCity.getCityId());
            }
        } else {
            if (!isWinner && team.getTargetCityId() != 0) {
                activity.getMapActivityMgr().autoMoveToCity(team, team.getTargetCityId());
            } else {
                // 胜利者继续战斗
                //activity.addTask(new CrossSuiTangAutoBattleTask(activity, System.currentTimeMillis(), getCity(team.getUserId()), battleTeam));
            }
        }
    }

    /*
     * 战斗后处理
     */
    private void battleAfter(CrossSuiTangCity city, CrossSuiTangBattlefieldTeam winner, CrossSuiTangBattlefieldTeam loser, CrossSuiTangBattleResult result) {
        // 同步战斗结果
        activity.getSyncActivityMgr().syncBattleResultMsg(city);
        /*if (loser.getTeam() != null) {
            long now = System.currentTimeMillis();
            CrossSuiTangTeam team = getTeam(loser.getTeamNo());
            if (team != null) {
                team.setWinTime(now);
                team.setWinTimes(0);
            }
        } else {
            // npc 死了，同步一下城市的血量等信息
            activity.getSyncActivityMgr().syncCity(city);
        }*/

        // 处理自动
        if (winner.getTeam() != null && activity.getMapActivityMgr().getNextMoveCity(winner.getTeamNo()) != null) {
            // 要跑，就不要加自动战斗的任务了，跑不了的再战斗
            return;
        } else if (winner.getTeam() != null && getTeam(winner.getTeamNo()) != null && getTeam(winner.getTeamNo()).isAutoBattle()) {
            //activity.addTask(new CrossSuiTangAutoBattleTask(activity, result.getBattleEndTime(), city, winner));
        }
    }

    /**
     * 自动战斗
     * @param city 城市数据
     */
    public void autoAttack(CrossSuiTangCity city) {
        List<CrossSuiTangBattlefieldTeam> teamList = new ArrayList<>();
        // 防守队列
        for (CrossSuiTangBattlefieldTeam team : city.getBattlefield().getDefTeamMap().values()) {
            if (team.getSoldierType() != 0) {
                continue;
            }
            teamList.add(team);
        }
        // 攻城队列
        for (CrossSuiTangBattlefieldTeam team : city.getBattlefield().getAtkTeamMap().values()) {
            if (team.getSoldierType() != 0) {
                continue;
            }
            teamList.add(team);
        }

        // 排序一下  根据到达时间排序,先到的排前面
        teamList.sort((o1, o2) -> {
            if (o1.getTeam() != null && o2.getTeam() != null) {
                return Long.compare(o1.getTeam().getTime(), o2.getTeam().getTime());
            } else if (o1.getTeam() != null) {
                return -1;
            } else if (o2.getTeam() != null) {
                return 1;
            } else {
                return 0;
            }
        });
        // 开打
        for (CrossSuiTangBattlefieldTeam team : teamList) {
            // 先检查下有没有预设目标
            if (team != null && team.getTeam() != null && getTeam(team.getTeamNo()).isAutoBattle()) {
                CrossSuiTangCity nextMoveCity = activity.getMapActivityMgr().getNextMoveCity(team.getTeamNo());
                if (nextMoveCity == null) {
                    autoAttack(city, team);
                }
            }
        }
    }

    /*
     * 自动战斗
     */
    public void autoAttack(CrossSuiTangCity city, CrossSuiTangBattlefieldTeam team) {
        if (activity == null) {
            return;
        }
        if (!activity.isBattleStep()) {
            return;
        }
        if (team == null) {
            return;
        }
        if (team.getTeam() == null) {
            return;
        }
        CrossSuiTangTeam userTeam = getTeam(team.getTeamNo());
        synchronized (getPlayerLock(team.getTeamNo())) {
            if (userTeam == null
                    || userTeam.getSoldierNum() == 0
                    || isOut(team.getTeamNo())) {
                // 战败了，就不要继续战斗了
                return;
            }
        }
        if (!userTeam.isAutoBattle()) {
            return;
        }
        long now = System.currentTimeMillis();
        if (userTeam.getCityId() != city.getCityId() || team.getLastBattleTime() > now) {
            // 城池不对，重新加自动战斗的任务
//            CrossSuiTangCity curCity = getCity(team.getTeamNo());
            //activity.addTask(new CrossSuiTangAutoBattleTask(activity, team.getLastBattleTime(), curCity, team));
            return;
        }
        // 寻找可以战斗的对象
        CrossSuiTangBattlefieldTeam enemy = autoFindEnemy(city, userTeam);
        if (enemy == null) {
            // 没找到可能是因为没有玩家可打，接着索敌
            //activity.addTask(new CrossSuiTangAutoBattleTask(activity, now + DateHelper.SECOND_MILLIONS, city, team));
            return;
        }
        handleBattle(city, team.getTeamNo(), enemy.getTeamNo(), enemy.getTeam() == null);
    }

    /*
     * autoFindEnemy
     */
    public CrossSuiTangBattlefieldTeam autoFindEnemy(CrossSuiTangCity city, CrossSuiTangTeam team) {
        if (activity == null) {
            return null;
        }
        synchronized (getCityLock(city)) {
            CrossSuiTangBattlefield battlefield = city.getBattlefield();
            if (battlefield == null) {
                return null;
            }
            CrossSuiTangUserData userData = activity.getUserData(team.getUserId());
            if (userData == null) {
                return null;
            }
            boolean isDef = Objects.equals(userData.getUnionUid(), city.getUnionId());
            if (isDef) {
                // 防守方从进攻阵营中索敌，且敌人都是玩家
                Map<Long, CrossSuiTangBattlefieldTeam> teamMap = battlefield.getAtkTeamMap();
                if (teamMap.isEmpty()) {
                    return null;
                }
                List<CrossSuiTangTeam> enemyList = new ArrayList<>();
                for (CrossSuiTangBattlefieldTeam teamTemp : teamMap.values()) {
                    CrossSuiTangTeam teamEnemy = getTeam(teamTemp.getTeamNo());
                    if (teamEnemy != null
                            && teamEnemy.getSoldierNum() >= 0
                            && teamEnemy.getCityId() == city.getCityId()) {
                        enemyList.add(teamEnemy);
                    }
                }
                if (enemyList.isEmpty()) {
                    return null;
                }
                enemyList.sort(Comparator.comparing(CrossSuiTangTeam::getSoldierNum));

                long enemyId = findEnemyUser(city, team.getUserId(), enemyList);
                return teamMap.get(enemyId);
            } else {
                // 进攻方则需要按照规则进行索敌，守城方玩家 > 攻城方玩家 > 守军
                Map<Long, CrossSuiTangBattlefieldTeam> teamMapDef = battlefield.getDefTeamMap();
                Map<Long, CrossSuiTangBattlefieldTeam> teamMapAtk = battlefield.getAtkTeamMap();
                List<CrossSuiTangTeam> enemyUserDefList = new ArrayList<>();
                List<CrossSuiTangTeam> enemyUserAttList = new ArrayList<>();
                List<CrossSuiTangBattlefieldTeam> enemyNpcList = new ArrayList<>();
                for (CrossSuiTangBattlefieldTeam teamTemp : teamMapDef.values()) {
                    if (teamTemp.getTeam() == null) {
                        if (teamTemp.getSoldierNum() >= 0) {
                            enemyNpcList.add(teamTemp);
                        }
                    } else {
                        CrossSuiTangTeam teamEnemy = getTeam(teamTemp.getTeamNo());
                        if (teamEnemy.getSoldierNum() >= 0
                                && teamEnemy.getCityId() == city.getCityId()) {
                            enemyUserDefList.add(teamEnemy);
                        }
                    }
                }
                for (CrossSuiTangBattlefieldTeam teamTemp : teamMapAtk.values()) {
                    CrossSuiTangTeam teamEnemy = getTeam(teamTemp.getTeamNo());
                    if (teamEnemy != null
                            && teamEnemy.getUserId() != team.getUserId()
                            && teamEnemy.getSoldierNum() >= 0
                            && getTeamStatus(team) == eSuiTangTeamStatus.Free
                            && teamEnemy.getCityId() == city.getCityId()) {
                        enemyUserAttList.add(teamEnemy);
                    }
                }
                enemyUserDefList.sort(Comparator.comparing(CrossSuiTangTeam::getSoldierNum));
                enemyUserAttList.sort(Comparator.comparing(CrossSuiTangTeam::getSoldierNum));
                enemyNpcList.sort(Comparator.comparing(CrossSuiTangBattlefieldTeam::getSoldierNum));
                // 找防守方
                long enemyId = findEnemyUser(city, team.getUserId(), enemyUserDefList);
                long NO_ENEMY = -1;
                if (enemyId != NO_ENEMY) {
                    return teamMapDef.get(enemyId);
                }
                // 找进攻方
                enemyId = findEnemyUser(city, team.getUserId(), enemyUserAttList);
                if (enemyId != NO_ENEMY) {
                    return teamMapAtk.get(enemyId);
                }
                // 找npc
                enemyId = findEnemyNpc(city, team.getUserId(), enemyNpcList);
                return teamMapDef.get(enemyId);
            }
        }
    }

    /*
     * findEnemyUser
     */
    private long findEnemyUser(CrossSuiTangCity city, long userId, List<CrossSuiTangTeam> enemys) {
        long NO_ENEMY = -1;
        if (city == null || activity == null) {
            return NO_ENEMY;
        }

        for (CrossSuiTangTeam enemy : enemys) {
            CrossSuiTangUserData enemyUser = activity.getUserData(enemy.getUserId());
            if (enemyUser != null && canAttackUser(city, userId, enemy.getUserId())) {
                return enemy.getUserId();
            }
        }
        return NO_ENEMY;
    }

    /*
     * findEnemyNpc
     */
    private long findEnemyNpc(CrossSuiTangCity city, long userId, List<CrossSuiTangBattlefieldTeam> enemys) {
        long NO_ENEMY = -1;
        if (city == null || activity == null) {
            return NO_ENEMY;
        }

        for (CrossSuiTangBattlefieldTeam enemy : enemys) {
            if (canAttackNpc(city, userId, enemy.getTeamNo())) {
                return enemy.getTeamNo();
            }
        }
        return NO_ENEMY;
    }

    /*
     * 是否可以攻击 npc
     */
    private boolean canAttackNpc(CrossSuiTangCity city, long userId, long enemyId) {
        if (city == null) {
            return false;
        }
        SuiTangCityConfig cityConfig = activity.getConfig().getCityConfigMap().get(city.getCityId());
        if (cityConfig == null) {
            return false;
        }
        CrossSuiTangUserData attUser = activity.getUserData(userId);
        if (Objects.equals(attUser.getUnionUid(), city.getUnionId())) {
            // 同商会不可以攻打
            return false;
        }

        CrossSuiTangTeam attUserTeam = attUser.getTeam();
        if (attUserTeam == null || attUserTeam.getCityId() != city.getCityId()) {
            // 玩家队伍不在对应的城市
            return false;
        }

        CrossSuiTangUserRound attUserRound = getCurUserRound(attUser);
        if (attUserRound == null || attUserRound.getActGroupId() < 0
                || attUserRound.getActGroupId() != city.getActGroupId()) {
            // 玩家在不同分组 或者 玩家没有分组
            return false;
        }

        CrossSuiTangUnionRound attUnionRound = getUnionRoundData(attUser.getUnionUid());
        if (attUnionRound == null || attUnionRound.isOut()) {
            // 进攻方或者防守方被淘汰
            return false;
        }

        if (getTeamStatus(attUserTeam) != eSuiTangTeamStatus.Free) {
            // 攻击者或者被攻击者在交战中或行军中
            return false;
        }

        // 保护时间内不可攻打
        if (activity.getCityActivityMgr().inProtectTime(city)) {
            return false;
        }

        // 活动阶段判断
        if (!activity.isBattleStep()) {
            return false;
        }

        synchronized (getCityLock(city)) {
            // 锁住城市，避免城市此时的队列信息改变
            CrossSuiTangBattlefield battlefield = city.getBattlefield();
            if (battlefield == null) {
                return false;
            }
            // 被攻击者是否是防守方
            Map<Long, CrossSuiTangBattlefieldTeam> enemyTeamMap = battlefield.getDefTeamMap();
            if (enemyTeamMap == null || enemyTeamMap.isEmpty()) {
                return false;
            }
            long now = System.currentTimeMillis();
            CrossSuiTangBattlefieldTeam enemyBattleTeam = enemyTeamMap.get(enemyId);
            if (enemyBattleTeam == null || enemyBattleTeam.getBattleCd() > now) {
                // 被攻击者的保护 CD 未到
                return false;
            }
            Map<Long, CrossSuiTangBattlefieldTeam> attackingTeamMap = battlefield.getAttackingTeamMap();
            if (attackingTeamMap == null
                    || attackingTeamMap.get(userId) != null || attackingTeamMap.get(enemyId) != null
            ) {
                // 攻击者或被攻击者在正在交战中
                return false;
            }
            Map<Long, CrossSuiTangBattlefieldTeam> atkTeamMap = battlefield.getAtkTeamMap();
            if (atkTeamMap == null) {
                return false;
            }
            for (CrossSuiTangBattlefieldTeam team : atkTeamMap.values()) {
                if (!Objects.equals(activity.getUserData(team.getTeamNo()).getUnionUid(), attUser.getUnionUid())
                        && team.getTeam().getTime() < now
                ) {
                    // 未清空其他商会玩家(非行军中)，不可以攻打 npc
                    return false;
                }
            }

            // 判断下是否可以打根据地
            if (cityConfig.getType() == eSuiTangCityType.CITY_TYPE_HOME.getType()) {
                // 先判断有没有守军
                List<CrossSuiTangBattlefieldTeam> tmpDefTeamMap = new ArrayList<>(city.getBattlefield().getDefTeamMap().values());
                int defCnt = 0;
                for (CrossSuiTangBattlefieldTeam battlefieldTeam : tmpDefTeamMap) {
                    if (battlefieldTeam.getSoldierType() != 0) {
                        continue;
                    }
                    CrossSuiTangUserData userData = activity.getUserData(battlefieldTeam.getTeam().getUserId());
                    if (userData == null) {
                        continue;
                    }
                    if (city.getUnionId().equals(userData.getUnionUid())) {
                        // 玩家
                        defCnt++;
                    }
                }
                if (defCnt > 0) {
                    // 可发起队数=阻击所需人数-守方玩家队数(仅根据地)
                    int canAttackTeamNUm = Math.max(0, city.getNeedDefensePeople() - defCnt);
                    // 当前进攻的队伍数量
                    int attackingCnt = 0;
                    List<CrossSuiTangBattlefieldTeam> tmpAttackingTeamMap = new ArrayList<>(city.getBattlefield().getAttackingTeamMap().values());
                    for (CrossSuiTangBattlefieldTeam battlefieldTeam : tmpAttackingTeamMap) {
                        if (battlefieldTeam.getSoldierType() == 0) {
                            continue;
                        }
                        // 城防军
                        attackingCnt++;
                    }
                    // 当前剩下可发起队数
                    if (canAttackTeamNUm <= attackingCnt) {
                        // 不可发起攻击
                        return false;
                    }
                }

            } else {
                // 非根据地
                for (CrossSuiTangBattlefieldTeam team : enemyTeamMap.values()) {
                    if (team.getTeam() != null && team.getTeam().getTime() < now) {
                        // 未清空防守商会玩家(非行军中)，不可以攻打 npc
                        return false;
                    }
                }
            }
        }

        return true;
    }

    /*
     * 是否可以攻击玩家
     */
    private boolean canAttackUser(CrossSuiTangCity city, long userId, long enemyId) {
        if (city == null) {
            return false;
        }
        CrossSuiTangUserData attUser = activity.getUserData(userId);
        CrossSuiTangUserData enemyUser = activity.getUserData(enemyId);
        if (Objects.equals(attUser.getUnionUid(), enemyUser.getUnionUid())) {
            // 同商会不可以攻打
            return false;
        }
        CrossSuiTangTeam attUserTeam = attUser.getTeam();
        CrossSuiTangTeam enemyUserTeam = enemyUser.getTeam();
        if (attUserTeam == null || enemyUserTeam == null
                || attUserTeam.getCityId() != city.getCityId()
                || enemyUserTeam.getCityId() != city.getCityId()
        ) {
            // 玩家队伍不在对应的城市
            return false;
        }

        CrossSuiTangUserRound attUserRound = getCurUserRound(userId);
        CrossSuiTangUserRound enemyUserRound = getCurUserRound(enemyId);
        if (attUserRound == null
                || enemyUserRound == null
                || attUserRound.getActGroupId() != enemyUserRound.getActGroupId()
        ) {
            // 玩家在不同分组 或者 玩家没有分组
            return false;
        }
        CrossSuiTangUnionRound attUnionRound = getUnionRoundData(attUser.getUnionUid());
        CrossSuiTangUnionRound enemyUnionRound = getUnionRoundData(enemyUser.getUnionUid());
        if (attUnionRound == null || attUnionRound.isOut()
                || enemyUnionRound == null || enemyUnionRound.isOut()) {
            // 进攻方或者防守方被淘汰
            return false;
        }
        // 活动阶段判断
        if (!activity.isBattleStep()) {
            return false;
        }

        synchronized (getCityLock(city)) {
            CrossSuiTangBattlefield battlefield = city.getBattlefield();
            if (battlefield == null) {
                return false;
            }
            // 被攻击者是否是防守方
            boolean isDef = Objects.equals(enemyUser.getUnionUid(), city.getUnionId());
            Map<Long, CrossSuiTangBattlefieldTeam> enemyTeamMap = isDef ? battlefield.getDefTeamMap() : battlefield.getAtkTeamMap();
            if (enemyTeamMap == null || enemyTeamMap.isEmpty()) {
                return false;
            }
            CrossSuiTangBattlefieldTeam enemyBattleTeam = enemyTeamMap.get(enemyId);
            if (enemyBattleTeam == null || enemyBattleTeam.getBattleCd() > System.currentTimeMillis()) {
                // 被攻击者的保护 CD 未到
                return false;
            }
            Map<Long, CrossSuiTangBattlefieldTeam> attackingTeamMap = battlefield.getAttackingTeamMap();
            if (attackingTeamMap == null
                    || attackingTeamMap.get(userId) != null || attackingTeamMap.get(enemyId) != null
            ) {
                // 攻击者或被攻击者在正在交战中
                return false;
            }
        }

        if (getTeamStatus(attUserTeam) != eSuiTangTeamStatus.Free
                || getTeamStatus(enemyUserTeam) != eSuiTangTeamStatus.Free) {
            // 攻击者或者被攻击者在交战中或行军中
            return false;
        }

        return true;
    }

    /**
     * 计算损兵比例
     */
    private BigDecimal calcBattleCostPercent(long myCount, long enemyCount) {
        if (activity == null) {
            return null;
        }
        SuiTangConfigSync config = activity.getConfig();
        if (config == null || !ActivityMgr.activityInTime(config.getActivityInfo())) {
            return null;
        }

        // 容错
        myCount = myCount <= 0 ? 1 : myCount;
        enemyCount = enemyCount <= 0 ? 1 : enemyCount;

        BigDecimal param1 = BigDecimal.valueOf(config.getParamConfig().getSuiTangSoldierLostParam().get(0));
        BigDecimal param2 = BigDecimal.valueOf(config.getParamConfig().getSuiTangSoldierLostParam().get(1));
        BigDecimal param3 = BigDecimal.valueOf(config.getParamConfig().getSuiTangSoldierLostParam().get(2));
        BigDecimal param4 = BigDecimal.valueOf(config.getParamConfig().getSuiTangSoldierLostParam().get(3));
        BigDecimal param5 = BigDecimal.valueOf(config.getParamConfig().getSuiTangSoldierLostParam().get(4));
        BigDecimal param6 = BigDecimal.valueOf(config.getParamConfig().getSuiTangSoldierLostParam().get(5));
        BigDecimal param7 = BigDecimal.valueOf(config.getParamConfig().getSuiTangSoldierLostParam().get(6));

        // 敌方兵数/我方兵数
        BigDecimal partSoldier = BigDecimal.valueOf(enemyCount).divide(BigDecimal.valueOf(myCount), 8, BigDecimal.ROUND_DOWN);
        // 参数1/参数2
        BigDecimal part12 = param1.divide(param2, 8, BigDecimal.ROUND_DOWN);
        // 参数3/参数4
        BigDecimal part34 = param3.divide(param4, 8, BigDecimal.ROUND_DOWN);
        // 参数5/参数6
        BigDecimal part56 = param5.divide(param6, 8, BigDecimal.ROUND_DOWN);

        BigDecimal partSoldier12 = BigDecimal.valueOf(Math.pow(partSoldier.doubleValue(), part12.doubleValue())).setScale(8, BigDecimal.ROUND_DOWN);

        BigDecimal result = partSoldier12.multiply(part34)
                .add(partSoldier.multiply(part56))
                .add(param7)
                .multiply(partSoldier)
                .setScale(8, BigDecimal.ROUND_DOWN);

        // 不能超过1
        if (result.compareTo(BigDecimal.ONE) > 0) {
            result = BigDecimal.ONE;
        }

        return result;
    }

    /**
     * 计算战功
     */
    private long calcZhanGong(long soldierCostNum, long mySoldierNum) {
        if (activity == null) {
            return 0;
        }
        SuiTangConfigSync config = activity.getConfig();
        if (config == null || !ActivityMgr.activityInTime(config.getActivityInfo())) {
            return 0;
        }

        BigDecimal param1 = BigDecimal.valueOf(config.getParamConfig().getSuiTangItemScoreParam().get(0));
        BigDecimal param2 = BigDecimal.valueOf(config.getParamConfig().getSuiTangItemScoreParam().get(1));
        BigDecimal param3 = BigDecimal.valueOf(config.getParamConfig().getSuiTangItemScoreParam().get(2));
        BigDecimal param4 = BigDecimal.valueOf(config.getParamConfig().getSuiTangItemScoreParam().get(3));
        BigDecimal costNum = BigDecimal.valueOf(soldierCostNum);
        BigDecimal one = BigDecimal.ONE;
        BigDecimal myNum = BigDecimal.valueOf(mySoldierNum);

        BigDecimal part2 = myNum.divide(param4, 8, BigDecimal.ROUND_DOWN); // 我方兵数/参数4
        BigDecimal part3 = param1.divide(param2, 8, BigDecimal.ROUND_DOWN); // 参数1/参数2

        BigDecimal value = one
                .add(part2.multiply(part3))
                .multiply(costNum)
                .multiply(param3);

        return value.setScale(0, BigDecimal.ROUND_DOWN).longValue();
    }

    public void addBattleResultMap(String scene, CrossSuiTangBattleResult battleResult) {
        synchronized (battleResultMap) {
            List<CrossSuiTangBattleResult> resultList = battleResultMap.computeIfAbsent(scene, k -> new ArrayList<>());
            resultList.add(battleResult);
            battleResultMap.put(scene, resultList);
        }
    }

    public void initCityBattleTask() {
        //activity.addTask(new CrossSuiTangCityTask(activity, System.currentTimeMillis(), 0, 0, eSuiTangWarType.WAR_TYPE_YIJUN));
//        Map<Integer, Map<eSuiTangWarType, Map<Integer, Map<Integer, CrossSuiTangCity>>>> cityMap = activity.getCrossSuiTangData().getCityMap();
//
//        cityMap.values().stream()
//                .flatMap(warMap -> warMap.values().stream())
//                .flatMap(groupMap -> groupMap.values().stream())
//                .flatMap(cityMapTemp -> cityMapTemp.values().stream())
//                .filter(this::isValidCity)
//                .forEach(this::processCity);
    }

    private boolean isValidCity(CrossSuiTangCity city) {
        return city != null && city.getBattlefield() != null && city.getBattlefield().getAttackingTeamMap() != null;
    }

    private void processCity(CrossSuiTangCity city) {
//        activity.addTask(new CrossSuiTangCityTask(activity, System.currentTimeMillis(), city.getCityId(), city.getActGroupId(), city.getWarType()));
        hasBattleTask.add(activity.getSceneKey(city.getCityId(), city.getWarType(), city.getActGroupId()));
    }


    public Map<String, List<CrossSuiTangBattleResult>> getBattleResultMap() {
        return battleResultMap;
    }
}
